SQL-子查询

子查询基本语法

  • 子查询可放于selectfromwherehavingexists(相关子查询)后
  1. 子查询放于小括号内
  • 子查询又可分为相关子查询非相关子查询
    • 相关子查询一般放置于where、having之后,需要从外部查询获取结果,其一般执行多次。

    • 非相关子查询与外部查询相互独立,一般仅执行一次。

放置于wherehaving

支持:标量子查询(单行子查询)、列子查询(多行子查询)、行子查询

  1. 此时子查询一般放在条件的右侧。
  2. 标量子查询使用单行操作符如>,=;列子查询使用多行操作符in/not in any/some/all
  • 标量子查询

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #查询最低工资大于50号部门最低工资的部门id及其最低工资
    select department_id, min(salary)
    from employees
    group by department_id
    having min(salary)> (
    select min(salary)
    from employees
    where department_id =50
    );

    注意:对分组后的数据进行筛选使用 having

  • 列子查询

    • 使用 in 修饰列子查询结果,返回符合列子查询结果的元素。
    • 使用 any/some 修饰列子查询结果,将查询列表与列子查询结果依次对比,返回存在一次比较满足要求的结果。
    • 使用 all 修饰列子查询结果,将查询列表与列子查询结果依次对比,返回所有比较均满足要求的结果。

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
      #返回其他工种中比job_id为'IT_PROG'部门任一工资低的员工的工号、姓名、jobid及工资
    select employee_id,last_name,job_id,salary
    from employees
    where salary< any(
    select salary
    from employees
    where job_id = 'IT_PROG'
    )
    and job_id<> 'IT_PROG';



    #### **放置于`select`后**

    仅支持:标量子查询,一般为非相关子查询

    - 示例:

    ```sql
    #查询各部门信息及员工人数

    #方式一 相关子查询
    select d.*,(
    select count(*)
    from employees e
    where e.department_id =d.department_id) num
    from departments d;

    #方式二 连接+gorup by
    select d.*,count(e.department_id) num
    from departments d
    left outer join employees e
    on d.department_id = e.department_id
    group by d.department_id;

    方式一中,子查询被执行多次,针对外部查询的每一个组元,都进行了一次子查询。

放置于from

支持:表子查询

子查询一般为非相关子查询,结果作为一个虚拟表返回给外部查询。

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #查询各部门信息及员工人数

    #方式一,非相关子查询
    select d.* ,ifnull(c,0) num
    from departments d
    left outer join (
    select department_id,count(*) c
    from employees
    group by department_id) n
    on n.department_id = d.department_id;

    此时子查询必须要添加别名(虚拟表的表名)